#include "ids.h"

IDS::IDS(struct Sbuff *sbuff)
{
	pSbuff = sbuff;
	portlist_head = NULL;
	portlist_tail = portlist_head;
	bSniffer = false;
	packetfd = 0;
	old_log_buff_count = 0;
}

IDS::~IDS()
{
	portlist_tail = NULL;
	delete portlist_tail;
	delete pSbuff;
	delete [] portlist_head;
}

void IDS::ProcessTcp()
{
	struct tcphdr *tcp_header = pSbuff->h.tcp_header;
	struct iphdr *ip_header = pSbuff->nh.ip_header;

	if(bSniffer)
		PrintTcpHeader(tcp_header);
	if(tcp_header->syn && !tcp_header->ack)
	{
		attack.synflood++;
		if(!attack.synflood)
			memcpy(&attack.synsbuff, pSbuff, sizeof(struct Sbuff))
	}
	CheckScanTcp(pSbuff);
	CheckDosLand(pSbuff);
	CheckDosWinnuke(pSbuff);
	CheckDosLongURL(pSbuff);
	CheckProbeCGI(pSbuff);
}


void IDS::ProcessUdp()
{
	struct udphdr *udp_header = pSbuff->h.udp_header;

	if(bSniffer)
		PrintUdpHeader(udp_header);
}

void IDS::ProcessIcmp()
{
	struct icmphdr *icmp_header = pSbuff->h.icmp_header;
	if(bSniffer)
		PrintIcmpHeader(icmp_header);
}

void IDS::ProcessIgmp()
{
	struct igmphdr *igmp_header = pSbuff->h.igmp_header;
	if(bSniffer)
		printf("hello igmphdr");
}

void IDS::DoLog(char *msg, const struct Sbuff *sbuffptr)
{
	time_t	ticks;
	char	sendbuff[MAXBUFFSIZE];
	struct	iphdr *ip_header = sbuffptr->nh.ip_header;

	printf("old_log_buff = %s\n", old_log_buff);

	if(!strcmp(old_log_buff, msg))
	{
		old_log_buff_count++;
		printf("old_log_buff_count = %d\n", old_log_buff_count);
		return;
	}

	if(old_log_buff_count)
	{
		ticks = time(NULL);
		memset(sendbuff,0,sizeof(sendbuff));

		snprintf(sendbuff, sizeof(sendbuff), "%s %s %s %d %s",
			inet_ntoa(ip_header->saddr),
			inet_ntoa(ip_header->daddr),
			"The last massage repeated",
			old_log_buff_count,
			FillSpace((char*) ctime(&ticks))
		);

		if(fputs(sendbuff,logfd) == EOF)
			ErrQuit("fputs");
	}
	
	if(strncpy(old_log_buff, msg, MAXBUFFSIZE) == NULL)
	{
		printf("strncpy error\n");
	}
	printf("old_log_buff now:%s \n", old_log_buff);
	ticks= time(NULL);
	memset(sendbuff, 0, sizeof(sendbuff));
	snprintf(sendbuff,sizeof(sendbuff),
		"%s %s %s %s",
		inet_ntoa(ip_header->saddr),
		inet_ntoa(ip_header->daddr),
		msg,
		FillSpace((char*)ctime(&ticks))
	);
	if(fputs(sendbuff,logfd) == EOF)
		ErrQuit("fputs");
	return;
}


bool IDS::FindPort(int port)
{
	bool bFind = false;
	struct OpenPort *temp;

	if(portlist_head->port == 1)
	{
		bFind = true;
		return bFind;
	}

	for(temp=portlist_head->next; temp; temp=temp->next)
	{
		if(port == temp->port)
		{
			bFind = true;
			break;
		}
	}
	return bFind;
}

void IDS::AddPortToList(int port)
{
	struct OpenPort *temp = malloc(sizeof(struct OpenPort));
	temp->port = port;
	temp->next = NULL;
	portlist_tail->next = temp;
	portlist_tail = portlist_tail->next;
}

void IDS::ProcessCFG()
{
	FILE *fp;
	char i[100];
	int t;
	int dport;

	portlist_head = malloc(sizeof(struct OpenPort));
	portlist_tail = portlist_head;
	portlist_head->port = 0;
	portlist_head->next = NULL;

	fp = fopen("./openport.conf", "r");
	if(!fp)
	{
		printf("OpenPort.conf is not exist: all port is defined open.\n");
		portlist_head->port = 1;
		return;
	}

	for(t=0; t<3000; t++)
	{
		memset(i, 0,sizeof(i));
		if(fgets(i, sizeof(i), fp) == NULL)
			break;
		if(i[0] == '#' || i[0] == '\n' || !isdigit(i[0]))
			continue;
		dport = atoi(i);
		if(dport)
		{
			AddPortToList(dport);
			printf("Add port %d to OpenPort List. \n", dport);
		}
	}
}

void IDS::LogStatus()
{
	struct Sbuff *sbuff;
	if(attack.synflood > MAX_SYN)
	{
		sbuff = &attack.synsbuff;
		DoLog("synflood", sbuff);
	}
	memset(&attack, sizeof(attack));
	//alarm(1);
}

void IDS::FinalQuit()
{	
	printf("\n %l IP packet received\n",log.ippacket);  
	printf("%l Bad IP packet\n",log.bad_ippacket);  
	printf("%l TCP packets\n",log.tcppacket);  
	printf("%l UDP packets\n",log.udppacket);  
	printf("%l ICMP packets\n",log.icmppacket);  
	printf("%l IGMP packets\n",log.igmppacket);  
	printf("%l Unknow packets\n",log.unknownpacket);  
	printf("%l Fragment\n",log.fragment);  
	printf("%l Total bytes\n",log.totalbytes);     
	printf("Bye!\n");  
	exit(0);  
}

void IDS::SetSniffer(bool sniffer)
{
	bSniffer = sniffer;
}


void IDS::CheckDosLand()
{
	struct iphdr *ip_header = pSbuff->nh.ip_header;
	struct tcphdr *tcp_header = pSbuff->h.tcp_header;

	if(!tcp_header->syn)
		return;
	if(ip_header->saddr != ip_header->daddr || tcp_header->source != tcp_header->dest)
		return;
	DoLog("land",pSbuff);
}


void IDS::CheckDosWinnuke()
{
	struct tcphdr *tcp_header = pSbuff->h.tcp_header;
	if(ntohs(tcp_header->dest) == 139 && tcp_header->urg)
		DoLog("winnuke", pSbuff);
}

void IDS::CheckDosLongURL()
{
	struct tcphdr *tcp_header = pSbuff->h.tcp_header;
	char * data = pSbuff->data;

	if(ntohs(tcp_header->dest) != 80  || !tcp_header->ack)
		return;
	if(strlen(data) >= MAX_URL_LEN)
		DoLog("Too_long_url", pSbuff);
	printf("%s", data);
}

void IDS::CheckProbeCGI()
{
	struct tcphdr *tcp_header = pSbuff->h.tcp_header;
	char * data = strlwr(pSbuff->data);

	if(ntohs(tcp_header->dest) != 80 || !tcp_header->ack || !tcp_header->psh)
		return;

	if(strstr(data, "showcode.asp")!= NULL)
		DoLog("showcode",pSbuff);
	if(strstr(data, "phf?") != NULL)
		DoLog("phf", pSbuff);
	if(strstr(data, "/glimpse") != NULL)
		DoLog("glimpse_cgi", pSbuff);
	if(strstr(data,"/htmlscript")!=NULL)  
		DoLog("htmlscript",pSbuff);  
	if(strstr(data,"/bin/sh")!=NULL)  
		DoLog("/bin/sh",pSbuff);  
	if(strstr(data,"test")!=NULL)  
		DoLog("test",pSbuff);  
	if(strstr(data,"asp..")!=NULL)  
		DoLog("asp..",pSbuff); 
}

void IDS::CheckScanTcp()
{
	struct tcphdr *tcp_header = pSbuff->h.tcp_header;
	char alter[100];

	if(tcp_header->syn && !tcp_header->ack && !FindPort(ntohs(tcphdr.dest)))
	{
		snprintf(alter, sizeof(alter), "SYN_to_unopen port %d", ntohs(tcp_header->dest));
		DoLog(alter, pSbuff);
	}

	if(tcp_header->res1)
		DoLog("queso", pSbuff);
	if(tcp_header->fin&&tcp_header->syn&&!tcp_header->rst&&!tcp_header->psh&&!tcp_header->ack&&!tcp_header->urg)
      	DoLog("SF_scan", pSbuff);
	if(!tcp_header->fin&&!tcp_header->syn&&!tcp_header->rst&&!tcp_header->psh&&!tcp_header->ack&&!tcp_header->urg)
		DoLog("NULL_scan", pSbuff);
	if(tcp_header->fin&&tcp_header->syn&&tcp_header->rst&&tcp_header->psh&&tcp_header->ack&&tcp_header->urg)
		DoLog("FULL_Xmas_scan", pSbuff);
	if(tcp_header->fin&&!tcp_header->syn&&!tcp_header->rst&&tcp_header->psh&&!tcp_header->ack&&tcp_header->urg)
      	DoLog("XMAS_Scan(FPU)", pSbuff);
}


void IDS::CheckDosPingofDeath()
{
	struct iphdr *ip_header = pSbuff->nh.ip_header;

	if(ip_header->protocol != 1)
		return;
	DoLog("ping_of_death",pSbuff);
}

void IDS::PrintIpHeader(const struct iphdr *iph)
{
	printf("IP ver=%d\n",iph->version);  
	printf("IP ihl=%d bytes\n",iph->ihl<<2);  
	printf("IP tos=%d\n",iph->tos);  
	printf("IP tot_len=%d\n",ntohs(iph->tot_len));  
	printf("IP id=%d",ntohs(iph->id));  
//	printf(" %c ",(iph->flag_off &htons(IP_MF))?'M':'-');  
//	printf("IP frag_off=ox%x",ntohs(iph->flag_off&htons(IP_OFFSET)));  
	printf("IP ttl=%d",iph->ttl);  
	printf("IP protocol=%d\n",iph->protocol);  
	printf("From %s  ",inet_ntoa(iph->saddr));  
   printf("To %s\n",inet_ntoa(iph->daddr)); 
}
void IDS::PrintTcpHeader(const struct tcphdr *tcph);
void IDS::PrintUdpHeader(const struct udphdr *udph);
void IDS::PrintIcmpHeader(const struct icmphdr *icmph);
void IDS::PrintIgmpHeader(const struct igmphdr *igmph);
char* IDS::FillSpace(char* str);    //do for DoLog
void IDS::ErrQuit(char *errbuff);